import EventDefines from "../Constants/EventDefines";
import Oriented from "../Constants/ConstDir";
import MainPlayer from "../Entity/MainPlayer";
import G from "../Utilities/Global";
import eState from "../Lib/StateMachine/eState";
import StateEvent from "../Lib/StateMachine/StateEvent";
import AnimationController from "./AnimationController";
import Constants from "../Constants/Constants";

/**
 * 移动控制类
 * created by Five on 2018年11月15日11:48:22
 */
const { ccclass, property } = cc._decorator;

@ccclass
export default class PlayerMoveController extends cc.Component {
    @property
    Speed: number = 0;

    // 父节点管理碰撞,子节点管理动画
    @property(cc.Node)
    SpineNode: cc.Node = null;

    private _position: cc.Vec2 = cc.Vec2.ZERO;
    private _rigidbody: cc.RigidBody = null;
    private _mainplayer: MainPlayer = null;
    private _sqauting: boolean = false;
    private _oriented: Oriented = Oriented.RIGHT;

    private _anim: AnimationController = null;

    start() {
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.keyDown, this);
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.keyUp, this);
        this._rigidbody = this.getComponent(cc.RigidBody);
        this._mainplayer = this.getComponent(MainPlayer);
        this._anim = new AnimationController(this.SpineNode, "role");
        this._anim.initClips();
        this._mainplayer.setAnim(this._anim);

        this.schedule(this.stepSound, 0.3);
    }

    onDestroy() {
        cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.keyDown, this);
        cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.keyUp, this);
    }

    update(dt: number) {
        // 只允许配置为可位移的状态下产生位移
        if (this._mainplayer.Fsm.Current.Moveable) {
            let x = this._position.x * dt;
            this.node.position = this.node.position.add(cc.v2(x, 0));
        }

        // 没有站立的时候,不停的下落     
        if (G().CurScene != null) {
            let y = this._position.y * dt;
            this.node.position = this.node.position.add(cc.v2(0, y));

            let down = this.node.position;
            let loc = G().Calc.PositionToLocation(G().Calc.DC(down));
            let entity = G().CurScene.MapData.GetWallByLocation(loc);
            if (entity)
                this._position.y = 0;
            else {
                this._position.subSelf(cc.v2(0, Constants.Gravity * dt * 5));
            }
        }

        // 没有速度的移动, 退出移动状态
        if (this._mainplayer.Fsm.CurrentState == eState.MOVE && this._position.mag() == 0)
            this._mainplayer.Fsm.Quit();
    }

    // 用于切换步伐
    private step: boolean = false;
    stepSound() {
        if (this._mainplayer.Fsm.CurrentState == eState.MOVE) {
            G().Sound.playSFX(this.step ? "role_walk1" : "role_walk2");
            this.step = !this.step;
        }
    }

    keyDown(event: cc.Event.EventKeyboard) {
        let state: StateEvent;
        switch (event.keyCode) {
            // @ts-ignore
            case cc.macro.KEY.d:
                if (this._mainplayer.Fsm.CurrentState == eState.IDLE) {
                    this._mainplayer.Fsm.ChangeState(eState.MOVE, state);
                }
                this._oriented = Oriented.RIGHT;
                this._position.x = this.Speed;
                this._sqauting = false;
                this.turn();
                break;
            // @ts-ignore
            case cc.macro.KEY.a:
                if (this._mainplayer.Fsm.CurrentState == eState.IDLE) {
                    this._mainplayer.Fsm.ChangeState(eState.MOVE, state);
                }
                this._oriented = Oriented.LEFT;
                this._position.x = -this.Speed;
                this._sqauting = false;
                this.turn();
                break;
            // @ts-ignore
            case cc.macro.KEY.space:
                if (this._position.y != 0)
                    return;
                // 打断前一个动作
                if (!this._mainplayer.Fsm.Current.Moveable) {
                    state = new StateEvent(null, () => {
                        // 下坠状态
                        if (this._rigidbody.linearVelocity.mag() == 0) {
                            this._mainplayer.Fsm.Quit();
                        } else {
                            this._mainplayer.Fsm.Quit();
                            console.log('droping');
                        }
                    });
                } else {
                    state = new StateEvent(null, () => {
                        this._mainplayer.Fsm.Back();
                    });
                }
                this._position.y = Constants.Gravity * 3;
                this._mainplayer.Fsm.ChangeState(eState.JUMP, state);
                this._sqauting = false;
                break;
            // @ts-ignore
            case cc.macro.KEY.z:
                state = new StateEvent(null, () => {
                    this._mainplayer.Fsm.Quit();
                    this._mainplayer.shot(this._oriented)
                });
                this._mainplayer.Fsm.ChangeState(eState.ATTACK, state);
                break;
            // @ts-ignore
            case cc.macro.KEY.j:
                state = new StateEvent(null, () => {
                    this._mainplayer.Fsm.Quit();
                    this._mainplayer.makeOrdestroy(this._oriented, this._sqauting);
                });
                this._mainplayer.Fsm.ChangeState(eState.ATTACK, state);
                break;
            // @ts-ignore
            case cc.macro.KEY.s:
                this._sqauting = true;
                this._mainplayer.Fsm.ChangeState(eState.SQAUT, state);
                break;
            // @ts-ignore
            case cc.macro.KEY.p:
                G().CurScene.mController.TimeFreeze(5);
                break;
        }
    }

    keyUp(event: cc.Event.EventKeyboard) {
        let state: StateEvent;
        switch (event.keyCode) {
            // @ts-ignore
            case cc.macro.KEY.d:
                if (this._mainplayer.Fsm.CurrentState == eState.MOVE)
                    this._mainplayer.Fsm.Quit();
                this._position = cc.Vec2.ZERO;
                break;
            // @ts-ignore
            case cc.macro.KEY.a:
                if (this._mainplayer.Fsm.CurrentState == eState.MOVE)
                    this._mainplayer.Fsm.Quit();
                this._position = cc.Vec2.ZERO;
                break;
            // @ts-ignore
            case cc.macro.KEY.s:
                this._sqauting = false;
                this._mainplayer.Fsm.Quit();
                break;
            // @ts-ignore
            case cc.macro.KEY.p:
                G().CurScene.mController.TimeFlowing();
                break;
        }
    }

    turn() {
        this.SpineNode.rotationY = this._oriented == Oriented.RIGHT ? 0 : 180;
    }
}